import get_proxy_cache from "./data.global.cache";
import get_proxy_status from "./data.global.status";
import get_proxy_trigger from "./data.global.trigger";

/** 全局项目事件中心 */
export default class GlobalDC {
	private static _trigger_: ReturnType<typeof get_proxy_trigger>;
	private static _cache_: ReturnType<typeof get_proxy_cache>;
	private static _status_: ReturnType<typeof get_proxy_status>;
	private static app_name: string;

	public static get Trigger(){
		return GlobalDC._trigger_;
	}
	public static get Cache(){
		return GlobalDC._cache_;
	}
	public static get Status(){
		return GlobalDC._status_;
	}

	public static get AppName(){
		return GlobalDC.app_name;
	}

	public static init(app_name: string){
		GlobalDC.app_name = app_name;
		GlobalDC._trigger_ = get_proxy_trigger(app_name);
		GlobalDC._cache_ = get_proxy_cache(app_name);
		GlobalDC._status_ = get_proxy_status(app_name);

		GlobalDC.listening();
	}

	private static _interval_call_token_map_: Map<string, {timestamp: number, interval: number, call: (td: number, now: number)=>any, that?: any}> = new Map();

	public static interval(interval: number, call: (td: number, now: number)=>any, thisArg?: any){
		let token = mtec.string.randomToken(7, 36, tlkn=>!GlobalDC._interval_call_token_map_.has(tlkn));
		GlobalDC._interval_call_token_map_.set(token, {timestamp: Date.now(), interval, call, that: thisArg??null});
		if(!GlobalDC.clock_pause && GlobalDC.clock_id==undefined){
			GlobalDC.clockRun();
		}
		return token;
	}

	public static clearInterval(token: string){
		if(!GlobalDC._interval_call_token_map_.has(token)) return void 0;

		GlobalDC._interval_call_token_map_.delete(token);

		if(GlobalDC._interval_call_token_map_.size == 0 && GlobalDC.clock_id!=undefined){
			GlobalDC.cleanClock();
		}
	}

	private static clock_id:number;
	private static clock_pause = false;
	private static clockRun(){
		GlobalDC.cleanClock();

		let now = Date.now();

		if(GlobalDC._interval_call_token_map_.size > 0){
			GlobalDC._interval_call_token_map_.forEach(v=>v.timestamp = now-v.interval);
		}

		GlobalDC.clock_id = setInterval(()=>{
			now = Date.now();
			GlobalDC._interval_call_token_map_.forEach(async v=>{
				if(now - v.timestamp >= v.interval){
					if(v.that){
						Reflect.apply(v.call, v.that, [now - v.timestamp, now]);
					}else{
						Reflect.get(v, 'call')(now - v.timestamp, now);
					}
					v.timestamp = now;
				}
			});
		}, mtec.cc.frameTime);
	}

	private static cleanClock(){
		if(GlobalDC.clock_id!=undefined){
			clearInterval(GlobalDC.clock_id);
			GlobalDC.clock_id = undefined;
		}
	}

	private static listening(){
		if(!GlobalDC.Cache.login_time || !mtec.time.sameDay(GlobalDC.Cache.login_time, Date.now())){
			GlobalDC.Cache.login_time = Date.now();
			GlobalDC.Trigger.NEW_DAY = true;
		}

		GlobalDC.interval(200, (td, now)=>{
			GlobalDC.Status.curr_time = now;
			if(!mtec.time.sameDay(GlobalDC.Cache.login_time, now)){
				GlobalDC.Cache.login_time = now;
				GlobalDC.Trigger.NEW_DAY = true;
			}
		});
	}
}
